package com.mushuilingfeng.ddd.user.domain.org.entity;

import cn.hutool.core.util.StrUtil;
import com.mushuilingfeng.ddd.user.domain.base.BaseEntity;
import com.mushuilingfeng.ddd.user.domain.base.BusinessException;
import com.mushuilingfeng.ddd.user.domain.base.DomainArgumentException;
import com.mushuilingfeng.ddd.user.domain.base.Ii8nCode;
import com.mushuilingfeng.ddd.user.domain.base.StatusEnum;
import com.mushuilingfeng.ddd.user.domain.org.repository.IDepartmentRepository;
import com.mushuilingfeng.ddd.user.domain.org.repository.IOrgRepository;
import com.mushuilingfeng.ddd.user.domain.org.service.IOrgService;
import com.mushuilingfeng.ddd.framework.factory.DomainServiceFactory;
import com.mushuilingfeng.ddd.framework.factory.DomainRepositoryFactory;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.Date;

/**
 * 机构
 *
 * @author
 * @date 2024/9/14
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class Org extends BaseEntity {
    private String orgCode;
    private String orgName;
    private String orgDesc;
    private String parentOrgCode;
    private Date setUpTime;
    private Integer status;
    private Integer orgLevel;

    @Override
    public void simpleCheckParams() {
        super.simpleCheckParams();
        if (StrUtil.isBlankIfStr(orgName)) {
            throw new DomainArgumentException("机构名称不能为空！");
        }
        if (StrUtil.isBlankIfStr(orgDesc)) {
            throw new DomainArgumentException("机构描述不能为空！");
        }
        if (!StrUtil.isBlankIfStr(parentOrgCode)) {
            // 检查父级机构是否存在、可用
            Org parentOrg = DomainRepositoryFactory.getRepository(IOrgRepository.class).getByOrgCode(parentOrgCode);
            if (null == parentOrg) {
                throw new DomainArgumentException("父级机构不存在！");
            }
            if (parentOrg.getStatus() != StatusEnum.OPEN.getCode()) {
                throw new DomainArgumentException("父级机构不可用！");
            }
        }
    }

    // 实体，自我检查字段合法性
    public void setOrgName(String orgName) {
        if (null == orgName) {
            throw new DomainArgumentException("机构名称不能为空");
        }
        if (orgName.length() > 10) {
            throw new DomainArgumentException("机构名称太长！");
        }
        if (orgName.length() < 5) {
            throw new DomainArgumentException("机构名称太短！");
        }
        this.orgName = orgName;
    }

    public void setOrgLevel(Integer orgLevel) {
        if (null != this.orgLevel) {
            throw new DomainArgumentException("orgLevel已经有值，不能重新设置！");
        }
        this.orgLevel = orgLevel;
    }

    @Override
    public void saveNew() {
        super.saveNew();
        if (null == this.orgCode) {
            setOrgCode(DomainServiceFactory.getDomainService(IOrgService.class).newOrgCode());
        }
        if (null == this.orgLevel) {
            setOrgLevel(1);
        }
        if (null != setUpTime) {
            setSetUpTime(new Date());
        }
        setStatus(StatusEnum.OPEN.getCode());
        DomainRepositoryFactory.getRepository(IOrgRepository.class).saveOrUpdate(this);
    }

    @Override
    public void delete() {
        IOrgRepository orgRepository = DomainRepositoryFactory.getRepository(IOrgRepository.class);
        // 存在子级机构，则不能删除
        if (orgRepository.existChildOrg(orgCode)) {
            throw new BusinessException(Ii8nCode.ORG_NOT_EMPTY);
        }
        orgRepository.delete(id);
    }

    public Org getParentOrg() {
        if (StrUtil.isBlankIfStr(parentOrgCode)) {
            return null;
        }
        return DomainRepositoryFactory.getRepository(IOrgRepository.class).getByOrgCode(parentOrgCode);
    }

    private void checkStatus() {
        if (StatusEnum.STOP.code == status) {
            throw new BusinessException(Ii8nCode.ORG_STATUS_NOT_OPEN);
        }
    }

    public void addChildOrg(Org childOrg) {
        checkStatus();
        if (orgLevel >= 2) {
            throw new BusinessException(Ii8nCode.ORG_LEVEL_NOT_ALLOWED);
        }
        childOrg.setOrgLevel(orgLevel + 1);
        childOrg.setParentOrgCode(parentOrgCode);
        childOrg.saveNew();
    }

    public void removeChildOrg(String childOrgCode) {
        checkStatus();
        IOrgRepository orgRepository = DomainRepositoryFactory.getRepository(IOrgRepository.class);
        Org childOrg = orgRepository.getByOrgCode(childOrgCode);
        if (null == childOrg) {
            throw new BusinessException(Ii8nCode.ORG_NOT_EXIST);
        }
        if (!orgCode.equals(childOrg.getParentOrgCode())) {
            throw new BusinessException(Ii8nCode.ORG_IS_NOT_TARGET_CHILD);
        }
        childOrg.delete();
    }

    public void addDepartment(Department department) {
        department.setOrgCode(orgCode);
        department.saveNew();
    }

    public void removeDepartment(String deptCode) {
        Department department = DomainRepositoryFactory.getRepository(IDepartmentRepository.class).getByDeptCode(deptCode);
        if (null == department) {
            throw new BusinessException(Ii8nCode.DEPT_NOT_EXIST);
        }
        if (!orgCode.equals(department.getOrgCode())) {
            throw new BusinessException(Ii8nCode.DEPT_IS_NOT_TARGET_CHILD);
        }
        department.delete();
    }

}
